"""
实战:
    用XPath来做一个简单的爬虫，爬取某个贴吧里的所有帖子，获取每个帖子的标题，连接和帖子中图片
1. 确定url地址
2. 确定抓取数据的位置 (抓取数据的时候,先对数据进行分组,遍历提取数据)
    分组拿到li列表
    for 遍历提取 标题 以及详情页的url
3. 从列表中进入到详情页 对详情页的url发送请求
    提取图片

    1.准备url(请求头)
    2.发送请求,获取响应
    3.提取数据
    4.保存
    面向对象的方式来写: 定义类 将爬虫的步骤封装成方法  定义一个run方法 在此方法中调用爬虫步骤
"""
import requests, time
from lxml import etree


class TieBaSpider(object):

    # 准备初始化数据
    def __init__(self, name):
        self.url = "https://tieba.baidu.com/f?kw={}".format(name)
        self.headers = {
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
        }
        self.base_url = "https://tieba.baidu.com"

    def send_request(self, url):
        """
        发送请求,获取响应
        :param url: 发送请求的url地址
        :return: 返回响应内容
        """
        response = requests.get(url, headers=self.headers)
        return response.content

    def parse_data(self, response):
        """
        数据解析的方法
        :param response: 响应数据
        :return: 提取出来的数据
        """
        # <!-- --> 再前端的时候 注释语法:xpath中如果html内容是被注释的,使用xpath获取不到数据
        # 将网页源码中的注释给替换成空
        response = response.decode().replace("<!--", "").replace("-->", "")
        # 将响应内容转换成element对象
        element = etree.HTML(response)
        # 对数据进行分组
        li_list = element.xpath("//ul[@id='thread_list']/li")[1:]

        data_list = []
        # 遍历列表 获取每一个列表中的数据
        for li in li_list[:2]:
            item = {}
            item["title"] = li.xpath(".//a[@class='j_th_tit ']/text()")[0]
            item["href"] = self.base_url + li.xpath(".//a[@class='j_th_tit ']/@href")[0]

            # 发送详情页的url地址的请求 进入详情页 提取详情页中tip的数据
            item["img_url_list"] = self.parse_detail_image(item["href"])
            data_list.append(item)

        # # 获取下一页的Url地址
        next_url = "https:" + element.xpath(".//a[@class='next pagination-item ']/@href")[0] if len(element.xpath(".//a[@class='next pagination-item ']/@href")) > 0 else None

        return data_list, next_url
        # return data_list

    def parse_detail_image(self, detail_url):
        """
        发送详情页请求 解析详情页中的图片url地址
        :param detail_url: 详情页的url
        :return: 返回多个图片的url地址列表
        """
        response = self.send_request(detail_url)
        # 将响应内容转换成element对象
        element = etree.HTML(response)
        img_url_list = element.xpath("//img[@class='BDE_Image']/@src")

        return img_url_list

    def save_data(self, data_list):
        """保存数据的方法"""
        # for data in data_list:
        #     print(data)
        # 第一部分保存文本
        import json, os
        data_json = json.dumps(data_list, ensure_ascii=False)
        if not os.path.exists('tieba_data'):
            os.mkdir('tieba_data')
        # a 追加写入
        with open("tieba_data/" + 'tieba_json.json', 'a') as f:
            f.write(data_json)

        # 第二部分保存图片到本地
        for data in data_list:
            # print(data)
            id_name = data.get('href').split('/')[-1]
            if not os.path.exists('tieba_data/' + id_name):
                os.mkdir('tieba_data/' + id_name)
            for img_url in data.get('img_url_list'):
                response = requests.get(img_url)
                img_name = img_url.split('/')[-1]
                with open('tieba_data/' + id_name + '/' + img_name, 'wb') as f:
                    f.write(response.content)

    def run(self):
        # 1. 准备url
        # 2. 发送请求获取响应
        # response = self.send_request(self.url)
        # data_list = self.parse_data(response)
        # self.save_data(data_list)

        next_url = self.url
        while True:
            time.sleep(3)
            if next_url is None:
                print('获取数据完毕')
                break
            print("=======" + next_url)
            response = self.send_request(next_url)
            # 3. 解析数据
            data_list, next_url = self.parse_data(response)
            # 4. 保存
            self.save_data(data_list)


if __name__ == '__main__':
    content = input("请输入查找的贴吧内容:")
    tieba = TieBaSpider(content)
    tieba.run()
